#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion

namespace GenericExampleParticleSystem
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        ContentManager content;
        //GraphicsDevice device;


        Vector2 lastMouseLocation;

        SpriteBatch background2D;
        SpriteFont font;

        public Game1()
        {
            //variable instanciation for the graphics card (device)
            graphics = new GraphicsDeviceManager(this);
            content = new ContentManager(Services);
            
            //define the skybox
            SkyBox skyBox = new SkyBox(this, "Content/Models/skybox", "Content/Shaders/skybox", "Content/Textures/SkyBox/cubeMap");
            this.Components.Add(skyBox);

            //define the LiDAR points as Particles
            //LidarPoints part = new LidarPoints(this, graphics, "Content/Textures/Particles/Particle_simple_small", "Content/Shaders/Particle", 99);
            GenericPointSpriteParticles part = new GenericPointSpriteParticles(this,graphics, "Content/Textures/Particles/Particle_simple_small", "Content/Shaders/Particle",10);
            part.myPosition = new Vector3(0, 0, -10);
            part.DrawOrder = 5000;  // Want it to be drawn last so give it a big number.
            //part.Rotate(new Vector3(0, 0, 0.5f),2.6f);
            this.Components.Add(part);
            

            //define a mesh above object to drape.
            //DrawMesh mesh = new DrawMesh(this, graphics, "Content/Textures/Mesh/meshTexture", "Content/Shaders/triangleColor");
            //this.Components.Add(mesh);

            //march the cubes
            /**double[] blah = new double[2];
            blah[0] = 5; blah[1] = 2;
            MarchingCubes march = new MarchingCubes(this, graphics, "Content/Textures/Mesh/meshTexture", "Content/Shaders/triangleColor", part, 0.25f);
            march.DrawOrder = 5001;
            this.Components.Add(march);**/
            
            // Remove the 60 fps cap.
            graphics.SynchronizeWithVerticalRetrace = false;

            //Window Size, and Resize
            Window.AllowUserResizing = true;
            Window.ClientSizeChanged += new EventHandler(Resize);
            Window.ScreenDeviceNameChanged += new EventHandler(DeviceChanged);
        }


        /// <summary>
        /// Should the user move the game screen over to another monitor.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DeviceChanged(object sender, EventArgs e)
        {
            Camera.myViewport = graphics.GraphicsDevice.Viewport;
            Camera.myViewport.MinDepth = 1f;
            Camera.myViewport.MaxDepth = 1000f;
        }

        /// <summary>
        /// Should the game window screen size change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Resize(object sender, EventArgs e)
        {
            Camera.myViewport.Width = Window.ClientBounds.Width;
            Camera.myViewport.Height = Window.ClientBounds.Height;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            Camera.Initialize();
            Camera.myViewport = graphics.GraphicsDevice.Viewport;
            Camera.myViewport.MinDepth = 1f;
            Camera.myViewport.MaxDepth = 1000f;            

            base.Initialize();
        }


        /// <summary>
        /// Load your graphics content.  If loadAllContent is true, you should
        /// load content from both ResourceManagementMode pools.  Otherwise, just
        /// load ResourceManagementMode.Manual content.
        /// </summary>
        /// <param name="loadAllContent">Which type of content to load.</param>
        protected override void LoadContent()
        {

            background2D = new SpriteBatch(graphics.GraphicsDevice);
            font = content.Load<SpriteFont>("Content/Fonts/default");

            lastMouseLocation = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
        }

         
        /// <summary>
        /// Unload your graphics content.  If unloadAllContent is true, you should
        /// unload content from both ResourceManagementMode pools.  Otherwise, just
        /// unload ResourceManagementMode.Manual content.  Manual content will get
        /// Disposed by the GraphicsDevice during a Reset.
        /// </summary>
        /// <param name="unloadAllContent">Which type of content to unload.</param>
        protected override void UnloadContent()
        {
            // TODO: Unload any ResourceManagementMode.Automatic content
            content.Unload();

            // TODO: Unload any ResourceManagementMode.Manual content
        }


        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            #region get mouse/kb info
            MouseState state = Mouse.GetState();
            Vector2 mouseMoved = new Vector2(lastMouseLocation.X - state.X, lastMouseLocation.Y - state.Y);
            lastMouseLocation = new Vector2(state.X, state.Y);
            #endregion
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            #region rotate camera
            //Camera.Rotate(new Vector3(1, 0, 0), mouseMoved.Y * 0.01f);
            //Camera.Rotate(new Vector3(0, 1, 0), mouseMoved.X * 0.01f);
            Camera.Rotate(mouseMoved.X * 0.01f,mouseMoved.Y * 0.01f, 0);

            //Camera.Rotate(mouseMoved.X * 0.01f,mouseMoved.Y * 0.01f, 0);
            //Camera.AwesomeRotate(mouseMoved.Y * 0.01f, mouseMoved.X * 0.01f);

            if (Keyboard.GetState().IsKeyDown(Keys.Q))
            { Camera.Translate(new Vector3(0, 0.25f, 0)); }
            if (Keyboard.GetState().IsKeyDown(Keys.E))
            { Camera.Translate(new Vector3(0, -0.25f, 0)); }
#endregion

            #region f-Keys
            /*if (Keyboard.GetState().IsKeyDown(Keys.F1))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 10;
            if (Keyboard.GetState().IsKeyDown(Keys.F2))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 100;
            if (Keyboard.GetState().IsKeyDown(Keys.F3))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 1000;
            if (Keyboard.GetState().IsKeyDown(Keys.F4))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 2000;
            if (Keyboard.GetState().IsKeyDown(Keys.F5))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 4000;
            if (Keyboard.GetState().IsKeyDown(Keys.F6))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 6000;
            if (Keyboard.GetState().IsKeyDown(Keys.F7))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 7000;
            if (Keyboard.GetState().IsKeyDown(Keys.F8))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 8000;
            if (Keyboard.GetState().IsKeyDown(Keys.F9))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 9000;
            if (Keyboard.GetState().IsKeyDown(Keys.F10))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleCount = 10000;
             * */
            #endregion 

            #region number pad

            if (Keyboard.GetState().IsKeyDown(Keys.NumPad0))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 1;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad1))
            { 
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 2; 
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad2))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 3;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad3))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 4;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad4))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 5;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad5))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 6;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad6))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 7;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad7))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 8;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad8))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 9;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.NumPad9))
            {
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSize = 10;
            }
            #endregion 

            #region old properties changing

            /*
            if (Keyboard.GetState().IsKeyDown(Keys.F11))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSystem = ParticleSystem.Ball;
            if (Keyboard.GetState().IsKeyDown(Keys.F12))
                ((GenericPointSpriteParticles)this.Components[1]).ParticleSystem = ParticleSystem.Explosion;

            if (Keyboard.GetState().IsKeyDown(Keys.C))
                ((GenericPointSpriteParticles)this.Components[1]).RandomColor = true;
            if (Keyboard.GetState().IsKeyDown(Keys.R))
            {
                ((GenericPointSpriteParticles)this.Components[1]).RandomColor = false;
                ((GenericPointSpriteParticles)this.Components[1]).particleColor = Color.Salmon;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.G))
            {
                ((GenericPointSpriteParticles)this.Components[1]).RandomColor = false;
                ((GenericPointSpriteParticles)this.Components[1]).particleColor = Color.YellowGreen;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.B))
            {
                ((GenericPointSpriteParticles)this.Components[1]).RandomColor = false;
                ((GenericPointSpriteParticles)this.Components[1]).particleColor = Color.CornflowerBlue;
            }*/
             
#endregion

            #region camera movement
            if (Keyboard.GetState().IsKeyDown(Keys.W))
                Camera.Translate(new Vector3(0, 0, -.1f));
            if (Keyboard.GetState().IsKeyDown(Keys.S))
                Camera.Translate(new Vector3(0, 0, .1f));
            if (Keyboard.GetState().IsKeyDown(Keys.A))
                Camera.Translate(new Vector3(-.1f, 0, 0));
            if (Keyboard.GetState().IsKeyDown(Keys.D))
                Camera.Translate(new Vector3(.1f, 0, 0));
#endregion
            

                        
            Camera.Update();

            base.Update(gameTime);
        }
        private void setupRect()
        {
            //vertices = new VertexPositionColor[4];
            //float myFloat =  (float)((GenericPointSpriteParticles)this.Components[1]).faceLocation;
            //vertices[0].Position = new Vector3(0, myFloat, 0f);
            //vertices[0].Color = Color.Red;
            //vertices[1].Position = new Vector3(100, myFloat, 0f);
            //vertices[1].Color = Color.Green;
            //vertices[2].Position = new Vector3(0, myFloat, 100);
            //vertices[2].Color = Color.Yellow;
            //vertices[3].Position = new Vector3(100, myFloat, 100);
            //vertices[3].Color = Color.Yellow;

            //vb = new VertexBuffer(device, sizeof(float) * 4 * 5,BufferUsage.WriteOnly);
            //vb.SetData(vertices);

            //short[] indicies = new short[4];
            //indicies[0] = 0;
            //indicies[1] = 1;
            //indicies[2] = 2;
            //indicies[3] = 3;

            //ib = new IndexBuffer(device, typeof(short), 4,BufferUsage.WriteOnly);
            //ib.SetData(indicies);



        }
        

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            // drawable components in this class
            //this.setupRect();
            base.Draw(gameTime);

            WriteText("FPS: " + FPS.GetFPS(gameTime).ToString(), new Vector2(1, 1), Color.Gold);
            //WriteText("Particle Count: " + ((LidarPoints)this.Components[1]).partCount.ToString(), new Vector2(1, font.LineSpacing), Color.White);
            //WriteText("Particle System: " + ((GenericPointSpriteParticles)this.Components[1]).ParticleSystem.ToString(), new Vector2(1, font.LineSpacing*2), Color.White);
            //if(!((GenericPointSpriteParticles)this.Components[1]).RandomColor)
            //    WriteText("Particle Color (RGB) or C for random: " + ((GenericPointSpriteParticles)this.Components[1]).particleColor.ToString(), new Vector2(1, font.LineSpacing * 3), Color.White);
            //else
            //    WriteText("Particle Color (RGB) or C for random: Random", new Vector2(1, font.LineSpacing * 3), Color.White);                       

        }

        private void WriteText(string text, Vector2 coords, Color color)
        {
            background2D.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
            background2D.DrawString(font, text, coords, color);
            background2D.End();
        }
    }
}
